import re
import redis
import random

import urllib3
import requests
from bs4 import BeautifulSoup
from scrapy_redis.defaults import START_URLS_KEY
from scrapy.utils.project import get_project_settings

from amac_spider.utils.ua_pool import get_random_ua


redis_connection_url = get_project_settings()['REDIS_URL']
urllib3.disable_warnings()


class BaseInsert(object):

    def __init__(self, name, url):
        self.name = name
        self.url = self.replace_res(url)
        self.server = self.connection_from_redis()
        self.random = random.random()
        self.params = {
            'rand': self.random,
            'size': 100,
            'page': 0
        }

    def connection_from_redis(self):
        return redis.StrictRedis.from_url(url=redis_connection_url)

    def connection_close(self):
        self.server.close()

    def replace_res(self, url):
        return re.sub(r'res', 'api', url, 1)

    def send_request(self, url, data):
        headers = {
            'Content-Type': 'application/json',
            'User-Agent': get_random_ua()
        }
        response = requests.post(url=url, headers=headers, params=self.params, json=data, verify=False,
                                 allow_redirects=False)
        if response.status_code == 200:
            try:
                return response.json()
            except Exception as e:
                print('结果进行json转化时发生错误')
                exit(0)
        else:
            print('响应状态码不正确，响应状态码为{}'.format(response.status_code))
            exit(0)

    def handle_args(self, url):
        args = '&'.join([k + '=' + str(v) for k, v in self.params.items()])
        full_url = url + '?{}'.format(args)
        return full_url

    def insert(self, page, url):
        for p in range(page):
            self.params['page'] = p
            full_url = self.handle_args(url)
            self.server.lpush(START_URLS_KEY % {'name': self.name}, full_url)

    def run(self):
        response = self.send_request(url=self.url, data={})
        max_page = response['totalPages']
        self.insert(max_page, self.url)
        self.connection_close()


class AoinProductInsert(BaseInsert):
    pass


class PofSubfundInsert(BaseInsert):
    pass


class CancelledManagerInsert(BaseInsert):
    pass


class PofSecuritiesInsert(BaseInsert):
    pass


class FundAccountInsert(BaseInsert):
    pass


class PofPersonInsert(BaseInsert):

    def __init__(self, name, url):
        super().__init__(name, url)
        self.url = url
        self.params = {
            'rand': self.random,
            'size': 40,
            'page': 0
        }

    def get_have_args_url(self, url):
        return url + '/personOrgList.html'

    def get_api_url(self, url):
        api_url = self.replace_res(url).rsplit('/', 1)[0] + '/personOrg'
        return api_url

    def send_request(self, url, data):
        headers = {'User-Agent': get_random_ua()}
        have_args_url = self.get_have_args_url(url)
        try:
            response = requests.get(url=have_args_url, headers=headers, verify=False)
            if response.status_code != 200:
                print('插入URL时发生错误，错误原因：响应状态码不为200，状态码为{}'.format(response.status_code))
                exit(0)
        except Exception as e:
            print('插入URL时发生错误，错误原因：请求发生异常，异常信息为{}'.format(e.args))
            exit(0)
        else:
            # response.encoding = response.apparent_encoding
            response.encoding = 'utf-8'
            soup = BeautifulSoup(response.text, 'lxml')
            args_list = soup.select('#orgType option')
            args_list = [args.text for args in args_list]
            return args_list

    def my_insert(self, page, url, query):
        for p in range(page):
            self.params['page'] = p
            full_url = self.handle_args(url) + '&query={}'.format(query)
            self.server.lpush(START_URLS_KEY % {'name': self.name}, full_url)

    def run(self):
        args_list = self.send_request(url=self.url, data=None)
        api_url = self.get_api_url(self.url)
        for args in args_list:
            data = {'orgType': args, 'page': 1}
            response = super().send_request(url=api_url, data=data)
            max_page = response['totalPages']
            if int(max_page) == 0:
                continue
            self.my_insert(max_page, url=api_url, query=args)
        self.connection_close()


class MutualFundManagerInsert(BaseInsert):

    def __init__(self, name, url):
        super().__init__(name, url)
        self.url = url
        self.params = {
            'pageNo': 1,
            'pageSize': 10
        }

    def get_max_page(self, page):
        div, mod = divmod(page, self.params['pageSize'])
        if mod == 0:
            return div
        else:
            return div + 1

    def send_request(self, url, data):
        headers = {
            'User-Agent': get_random_ua()
        }
        response = requests.get(url=url, headers=headers, params=data, verify=False, allow_redirects=False)
        if response.status_code == 200:
            try:
                res = response.json()
            except Exception as e:
                print('结果进行json转化时发生错误')
                exit(0)
            else:
                code = int(res.get('code', 0))
                if code == 200:
                    return response.json()
                else:
                    print('响应结果中的code状态码不正确，code状态码为：{}'.format(code))
                    exit(0)
        else:
            print('响应状态码不正确，响应状态码为{}'.format(response.status_code))
            exit(0)

    def insert(self, page, url):
        for i in range(1, page+1):
            full_url = self.handle_args(url)
            self.server.lpush(START_URLS_KEY % {'name': self.name}, full_url)

    def run(self):
        response = self.send_request(url=self.url, data=self.params)
        self.params['pageSize'] = 100
        page = response['data']['data']['total']
        max_page = self.get_max_page(page)
        self.insert(max_page, self.url)
        self.connection_close()


class FundManagerInsert(BaseInsert):
    pass
